package com.study.util;

import com.study.annotation.NeedSetValue;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: chenhs
 * @date: Created in 16:42 2019/11/26
 **/
@Component
public class BeanUtil implements ApplicationContextAware {


    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (this.applicationContext == null) {
            this.applicationContext = applicationContext;
        }
    }

    public void setFieldValue4Collection(Collection col) throws Exception {
        //Order对象
        Class<?> clazz = col.iterator().next().getClass();

        Field[] fields = clazz.getDeclaredFields();

        Map<String, Object> cache = new HashMap<>(8);

        for (Field needField : fields) {
            NeedSetValue sv = needField.getAnnotation(NeedSetValue.class);
            if (sv == null) {
                continue;
            }
            needField.setAccessible(true);

            //1.调用Bean
            Object been = this.applicationContext.getBean(sv.beenClass());

            //2.获取调用方法
            Method method = sv.beenClass().getMethod(sv.method(), clazz.getDeclaredField(sv.param()).getType());

            //3.入参对象
            Field paramField = clazz.getDeclaredField(sv.param());

            paramField.setAccessible(true);

            //4.值的来源
            Field targetField = null;
            Boolean needInnerField = !StringUtils.isEmpty(sv.targetField());

            String keyPrefix = sv.beenClass() + "-" + sv.method() + "-" + sv.targetField();

            //去获取结果
            for (Object obj : col) {
                //入参对象值（即customerId = 110）
                Object paramValue = paramField.get(obj);
                if (paramValue == null) {
                    continue;
                }
                Object value;

                /**
                 * 先去拿缓存 （com.study.dao.UserDao.class-find-name100）
                 * 获取每个customerId对应的name
                 */
                String key = keyPrefix + paramValue;
                if (cache.containsKey(key)) {
                    value = cache.get(key);
                }else{
                    value = method.invoke(been, paramValue);
                    if (needInnerField) {
                        if (value != null) {
                            if (targetField == null) {
                                targetField = value.getClass().getDeclaredField(sv.targetField());
                                targetField.setAccessible(true);
                            }
                            value = targetField.get(value);
                        }
                    }
                    cache.put(key, value);
                }
                //为customerName赋值
                needField.set(obj, value);
            }

        }

    }


}
